//======================================================================
// FileName: pr_seq_gen.cpp
// Brief:    Common function of generating pseudo-random sequence
// Author:   wenwu
// History of Changes
//        Date|       Author|        Version|        Description
// -----------|-------------|---------------|-------------------
//  2021-08-13|      wenwu  |          0.0.1|    
//======================================================================

#include "pr_seq_gen.h"


#define fopen_s(pFile,filename,mode) ((*(pFile))=fopen((filename),  (mode)))==NULL



// Generate pseudo-random sequence(gold sequence)
void pr_seq_gen(IN uint32 uwCInit, IN uint32 uwSeqLen, OUT char SeqData[])
{
    uint32 m;
    uint32 x1 = 0, x2 = 0;
    
    pr_seq_init(uwCInit, &x1, &x2);

    for (m = 0; m < uwSeqLen; m++)
    {
        pr_seq_next_gen(&x1, &x2);
        // c(n) = (x1(n+Nc)+x2(n+Nc))%2
        SeqData[m] = (GETBIT(x1, 30) + GETBIT(x2, 30)) & 1;
    }
}


// Generate m-sequence x1 and x2
void pr_mseq_gen(IN uint32 uwCInit, IN uint32 uwSeqLen, OUT uint32 *pX1, OUT uint32 *pX2)
{
    uint32 m;
    
    pr_seq_init(uwCInit, pX1, pX2);

    for (m = 0; m < uwSeqLen; m++)
    {
        pr_seq_next_gen(pX1, pX2);
    }
}

// Update scram sequence x1 and x2
void pr_scramseq_up(IN uint32 uwSeqLen, INOUT uint32 *pX1, INOUT uint32 *pX2)
{
    uint32 m;

    for (m = 0; m < uwSeqLen; m++)
    {
		pr_seq_next_gen_for_scram(pX1, pX2);
    }
}

// Generate initial m-sequence x1 and x2
void pr_seq_init(IN uint32 uwCInit, OUT uint32 *pX1, OUT uint32 *pX2)
{
    uint32 i;

    *pX1 = 1;
    *pX2 = uwCInit;

    for (i = 31; i < NC; i++)
    {
        pr_seq_next_gen(pX1, pX2);
    }
}


// Generate next m-sequence x1 and x2
// Iterative shift to x1 and x2,and save 31 bits 
// Notes: x1(n+31)=(x1(n+3)+x1(n))%2
//        x2(n+31)=(x2(n+3)+x2(n+2)+x2(n+1)+x2(n))%2
void pr_seq_next_gen(INOUT uint32 *pX1, INOUT uint32 *pX2)
{
    uint32 TempBit1, TempBit2;

    TempBit1 = (GETBIT(*pX1, 3) + GETBIT(*pX1, 0)) & 1;
    TempBit2 = (GETBIT(*pX2, 3) + GETBIT(*pX2, 2) + GETBIT(*pX2, 1) + GETBIT(*pX2, 0)) & 1;

    *pX1 = (*pX1 >> 1) | (TempBit1 << 30);
    *pX2 = (*pX2 >> 1) | (TempBit2 << 30);
}



// Generate pseudo-random sequence(gold sequence) for scrambling code
void pr_seq_gen_scram_code(IN uint32 uwCInit, IN uint32 uwSeqLen, OUT char SeqData[])
{
	uint32 x1, x2, val;
	uint32 i;

	pr_seq_init_for_scram(uwCInit, &x1, &x2);

    val = (char)(x1 ^ x2) & 1;

	// Generate gold sequence for scrambling code
    for (i = 0; i < uwSeqLen; i++)
    {
        SeqData[i] = val;
        pr_seq_next_gen_for_scram(&x1, &x2);
        val = (char)(x1 ^ x2) & 1;
    }
}

// Generate initial pseudo-random sequence x1 and x2 for scrambling code
void pr_seq_init_for_scram(IN uint32 uwCInit, OUT uint32 *pX1, OUT uint32 *pX2)
{
	uint32 i, x1, x2, val;
	FILE  *Fp;

	x1 = 1;
	x2 = uwCInit;
	if (ULTEST_PRINTFLAG)
	{
		fopen_s(&Fp, "Result/PUSCHTestData/posteqData/descramb_para_data.am", "a+");
		fprintf(Fp, "%-32.32s%08X\n", "x1_init", x1); // x1 init
		fprintf(Fp, "%-32.32s%08X\n", "x2_init", x2); // x2 init
	}

	val = (char)((x1 & 1) ^ ((x1 >> 3) & 1));
	x1 = x1 | (val << 31);

	val = (char)((x2 & 1) ^ ((x2 >> 1) & 1) ^ ((x2 >> 2) & 1) ^ ((x2 >> 3) & 1));
	x2 = x2 | (val << 31);

	// Calculate C init value:
	for (i = 0; i < Nc; i++)
	{
		pr_seq_next_gen_for_scram(&x1, &x2);
	}

	if (ULTEST_PRINTFLAG)
	{
		fprintf(Fp, "%-32.32s%08X\n", "x1_init_1600", x1); // x1 init
		fprintf(Fp, "%-32.32s%08X\n", "x2_init_1600", x2); // x2 init
		fclose(Fp);
	}

	*pX1 = x1;
	*pX2 = x2;
}

// Generate next m-sequence x1 and x2 for scrambling code
// Iterative shift to x1 and x2,and save 31 bits 
// Notes: x1(n+31)=(x1(n+3)+x1(n))%2
//        x2(n+31)=(x2(n+3)+x2(n+2)+x2(n+1)+x2(n))%2
void pr_seq_next_gen_for_scram(INOUT uint32 *pX1, INOUT uint32 *pX2)
{
	uint32 x1, x2, val;

	x1 = *pX1;
	x2 = *pX2;

    x1 = x1 >> 1;
    val = (x1 & 1) ^ ((x1 >> 3) & 1);
    x1 = x1 | (val << 31);

    x2 = x2 >> 1;
    val = (x2 & 1) ^ ((x2 >> 1) & 1) ^ ((x2 >> 2) & 1) ^ ((x2 >> 3) & 1);
    x2 = x2 | (val << 31);

    *pX1 = x1;
    *pX2 = x2;
}


